﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MadProps.Tests.ChangeTrackingTests
{
    [TestClass]
    public class MasterDetailUndoRedoExample
    {
        public class Master : BindableModel
        {
            [Meta.Tracking(Tracking.Tagalong)]
            public readonly IProp<Detail> SelectedDetail;
        }

        [Meta.Tracking(Tracking.Tracked)]
        public class Detail : BindableModel
        {
            public readonly IProp<string> Name;
        }

        [TestInitialize]
        public void Setup()
        {
            master = new Master();
            detail1 = new Detail();
            detail2 = new Detail();
            master.SelectedDetail.Value = detail1;

            tracker = new ChangeTracking.ChangeTracker();
            tracker.Subscribe(master);
        }

        Master master;
        Detail detail1;
        Detail detail2;
        ChangeTracking.ChangeTracker tracker;

        Detail SelectedDetail
        {
            get { return master.SelectedDetail.Value; }
            set { master.SelectedDetail.Value = value; }
        }

        int UndoableCount { get { return tracker.UndoStack.Count(); } }
        int RedoableCount { get { return tracker.RedoStack.Count(); } }

        void Undo() { tracker.Undo(); }
        void Redo() { tracker.Redo(); }

        [TestMethod]
        public void MyTestMethod()
        {
            Assert.AreEqual(0, UndoableCount);
            Assert.AreSame(detail1, SelectedDetail);

            detail1.Name.Value = "detail 1";
            Assert.AreEqual(1, UndoableCount);

            Undo();
            Assert.AreEqual(0, UndoableCount);
            Assert.AreEqual(1, RedoableCount);
            Assert.AreEqual("", detail1.Name.Value);
            Assert.AreSame(detail1, SelectedDetail);

            Redo();
            Assert.AreEqual(1, UndoableCount);
            Assert.AreEqual(0, RedoableCount);
            Assert.AreEqual("detail 1", detail1.Name.Value);
            Assert.AreSame(detail1, SelectedDetail);

            SelectedDetail = detail2;
            Assert.AreEqual(1, UndoableCount);
            Assert.AreEqual(0, RedoableCount);

            Undo();
            Assert.AreEqual(0, UndoableCount);
            Assert.AreEqual(1, RedoableCount);
            Assert.AreEqual("", detail1.Name.Value);
            Assert.AreSame(detail1, SelectedDetail);

            Redo();
            Assert.AreEqual(1, UndoableCount);
            Assert.AreEqual(0, RedoableCount);
            Assert.AreEqual("detail 1", detail1.Name.Value);
            Assert.AreSame(detail1, SelectedDetail);

            SelectedDetail = detail2;
            Assert.AreEqual(1, UndoableCount);
            Assert.AreEqual(0, RedoableCount);

            detail2.Name.Value = "detail 2";
            Assert.AreEqual(2, UndoableCount);
            Assert.AreEqual(0, RedoableCount);

            Undo();
            Assert.AreEqual(1, UndoableCount);
            Assert.AreEqual(1, RedoableCount);
            Assert.AreEqual("", detail2.Name.Value);
            Assert.AreSame(detail2, SelectedDetail);

            Undo();
            Assert.AreEqual(0, UndoableCount);
            Assert.AreEqual(2, RedoableCount);
            Assert.AreEqual("", detail1.Name.Value);
            Assert.AreSame(detail1, SelectedDetail);

            Redo();
            Assert.AreEqual(1, UndoableCount);
            Assert.AreEqual(1, RedoableCount);
            Assert.AreEqual("detail 1", detail1.Name.Value);
            Assert.AreSame(detail1, SelectedDetail);

            Redo();
            Assert.AreEqual(2, UndoableCount);
            Assert.AreEqual(0, RedoableCount);
            Assert.AreEqual("detail 2", detail2.Name.Value);
            Assert.AreSame(detail2, SelectedDetail);
        }
    }
}
